home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 January: Mac OS SDK / Dev.CD Jan 96 SDK / Dev.CD Jan 96 SDK1.toast / Development Kits (Disc 1) / AOCE / Development Tools / Sample Code / Catalog Service Access Module / DTS Sample CSAM / Src / DTSSampleCSAM.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-03  |  8.2 KB  |  306 lines  |  [TEXT/KAHL]

  1. /*
  2.  * DTSSampleCSAM.c
  3.  * Copyright © 1992-93 Apple Computer Inc. All Rights Reserved.
  4.  *
  5.  * This is a simple CSAM (Catalog Service Access Module)
  6.  * for AOCE. It is based on the example written by OCE
  7.  * engineering. This sample calls the Personal Directory
  8.  * routines to do it's work. Since it doesn't use the
  9.  * Authentication interface, only "guest" access is provided.
  10.  *
  11.  * The functions in this file are called by the driver
  12.  * "glue" file that is linked at the start of the DRVR
  13.  * code segment. Note that the driver glue used here is
  14.  * not identical with either MPW ('DRVW' resource) or
  15.  * THINK (Device Driver Project option). As noted in
  16.  * the introduction to the driver glue file, this driver
  17.  * must be linked as a pure code segment.
  18.  *
  19.  * DTS Sample CSAM is based on sample code written by
  20.  * Steve Fisher, Eric Trehus, and Mike Cleron of Apple
  21.  * OCE engineering.
  22.  */
  23.  
  24. #include "DTSSampleCSAM.h"
  25. #ifdef THINK_C
  26. #include <ASM.h>
  27. #pragma parameter __D0 __MyGetA4()
  28. long        __MyGetA4(void) = 0x200C;    /* move.l a4, d0 */
  29. #endif
  30. #define USER_STATUS    (pb->ioResult)
  31. #define DCTL    (*devCtlEnt)            /* Driver control record    */
  32.  
  33.  
  34. /*
  35.  * Note: OpenDRVR must be called synchronously as it
  36.  * allocates memory.
  37.  */
  38. OSErr
  39. OpenDRVR(
  40.         register CntrlParam        *pb,
  41.         register DCtlPtr        devCtlEnt
  42.     )
  43. {
  44.         register DTSSampleCSAMInfoPtr    infoPtr;
  45.         StringHandle                    dsamName;
  46.         RString                            dsamRStringName;
  47.         short                            i;
  48. #define PB        (INFO.dirParamBlock)
  49. #define INST    (PB.instantiateDSAMPB)
  50.  
  51.         if (pb->ioCompletion != NULL)
  52.             USER_STATUS = openErr;                    /* Synchronous only    */
  53.         else {        
  54.             USER_STATUS = noErr;
  55.             infoPtr = (DTSSampleCSAMInfoPtr) DCTL.dCtlStorage;
  56.             if (infoPtr == NULL) {
  57.                 /*
  58.                  * First call: initialize our private data area.
  59.                  */
  60.                 infoPtr = (DTSSampleCSAMInfoPtr) NewPtrSysClear(
  61.                                 sizeof (DTSSampleCSAMInfo)
  62.                             );
  63.                 USER_STATUS = MemError();
  64.                 if (USER_STATUS == noErr && infoPtr == NULL)
  65.                     USER_STATUS = memFullErr;        /* Can't happen        */
  66.                 if (USER_STATUS == noErr) {
  67.                     DCTL.dCtlStorage = (Handle) infoPtr;
  68. #ifdef THINK_C
  69.                     INFO.originalA4 = __MyGetA4();
  70. #endif
  71.                 }
  72. #if DEBUG_LOG
  73.                 if (USER_STATUS == noErr) {
  74.                     INFO.auditPtr = InitAudit(kCSAMCreatorID, 64, TRUE, FALSE);
  75.                     LogText('DRVR', "\pDTSSampleCSAM Start");
  76.                 }
  77. #endif
  78.                 for (i = 0; USER_STATUS == noErr && i < kNumIcons; i++)
  79.                     USER_STATUS = GetCSAMIcon(infoPtr, i);
  80.                 LogStatus('DRVR', USER_STATUS, "\pGetCSAMIcon");
  81.                 if (USER_STATUS == noErr) {
  82.                     /*
  83.                      * We have a control block and the icons, now
  84.                      * instantiate the CSAM
  85.                      */
  86.                     dsamName = GetString(kCSAMName);
  87.                     if (dsamName == NULL)
  88.                         USER_STATUS = resNotFound;
  89.                     else {
  90.                         HLock((Handle) dsamName);
  91.                         USER_STATUS = MemError();
  92.                     }
  93.                     LogStatus('DRVR', USER_STATUS, "\pGetString(kCSAMName)");
  94.                 }
  95.                 if (USER_STATUS == noErr) {
  96.                     /*
  97.                      * Setup the parameter block. Note that
  98.                      * NewPtrSysClear initialized all fields
  99.                      * to zero. DirInstantiateDSAM requires the
  100.                      * dsRefNum to be zero.
  101.                      */
  102.                     OCEPToRString(
  103.                         *dsamName,
  104.                         smRoman,
  105.                         &dsamRStringName,
  106.                         kRStringMaxBytes
  107.                     );
  108.                     ReleaseResource((Handle) dsamName);
  109.                 }
  110.                 if (USER_STATUS == noErr) {
  111.                     /*
  112.                      * We're almost there. All we need to do now is to
  113.                      * tell the CSAM Manager our name and the names of
  114.                      * the functions to call when something happens in
  115.                      * our little world.
  116.                      *
  117.                      * This sample CSAM does not use Authentication
  118.                      * procedure callbacks.
  119.                      */
  120.                     INST.dsamName            = &dsamRStringName;
  121.                     INST.dsamKind            = kCSAMCreatorID;
  122.                     INST.dsamData            = (Ptr) infoPtr;
  123.                     INST.dsamDirProc        = (ProcPtr) CSAM_DSProc;
  124.                     INST.dsamDirParseProc    = (ProcPtr) CSAM_DSParseProc;
  125.                     INST.dsamAuthProc        = NULL;
  126.                     USER_STATUS = DirInstantiateDSAM(&PB);
  127.                     LogStatus('DRVR', USER_STATUS, "\pDirInstantiateDSAM");
  128.                 }
  129.             }
  130.         }
  131.         return (USER_STATUS);
  132. #undef PB
  133. #undef INST
  134. }
  135.  
  136. /*
  137.  * This sample CSAM does not use Prime calls. They may be
  138.  * needed for CSAM's that need periodic time.
  139.  */
  140. OSErr
  141. PrimeDRVR(
  142.         register CntrlParam        *pb,
  143.         register DCtlPtr        devCtlEnt
  144.     )
  145. {
  146. #pragma unused (devCtlEnt)
  147.         USER_STATUS = paramErr;
  148.         LogStatusX('DRVR', USER_STATUS, "\pPrimeDRVR");
  149.         return (paramErr);
  150. }
  151.  
  152.  
  153. /*
  154.  * This sample CSAM does not use Control calls. They might
  155.  * be needed in order to support the KillIO call.
  156.  */
  157. OSErr
  158. ControlDRVR(
  159.         register CntrlParam        *pb,
  160.         register DCtlPtr        devCtlEnt
  161.     )
  162. {
  163. #pragma unused (devCtlEnt)
  164.         USER_STATUS = controlErr;
  165.         LogStatusX('DRVR', USER_STATUS, "\pControlDRVR");
  166.         return (controlErr);
  167. }
  168.  
  169.  
  170. /*
  171.  * This sample CSAM does not use Status calls.
  172.  */
  173. OSErr
  174. StatusDRVR(
  175.         register CntrlParam        *pb,
  176.         register DCtlPtr        devCtlEnt
  177.     )
  178. {
  179. #pragma unused (devCtlEnt)
  180.         USER_STATUS = statusErr;
  181.         LogStatusX('DRVR', USER_STATUS, "\pStatusDRVR");
  182.         return (statusErr);
  183. }
  184.  
  185. /*
  186.  * Close deletes all storage allocated by OpenDRVR.
  187.  * Note that Close uses Memory Manager calls and,
  188.  * hence, must not be called at interrupt time
  189.  * or from an I/O completion routine.
  190.  */
  191. OSErr
  192. CloseDRVR(
  193.         register CntrlParam        *pb,
  194.         register DCtlPtr        devCtlEnt
  195.     )
  196. {
  197.         register DTSSampleCSAMInfoPtr    infoPtr;
  198.         CatalogInfoPtr                    catalogInfoPtr;
  199.         short                            i;
  200.         Handle                            iconHandle;
  201.  
  202.         LogTextX('CLOS', "\pCalling Close Driver");
  203.         USER_STATUS = noErr;
  204.         infoPtr = (DTSSampleCSAMInfoPtr) DCTL.dCtlStorage;
  205.         if (infoPtr != NULL) {
  206.             /*
  207.              * Go through the private storage carefully to
  208.              * delete all information that was allocated by
  209.              * our routines. Note that the order of operation
  210.              * was carefully chosen to make sure we make exactly
  211.              * one attempt to delete an item of information,
  212.              * even if some process fails because of an error.
  213.              *
  214.              * First, dump the storage used by our directory icons.
  215.              */
  216.             for (i = 0; USER_STATUS == noErr && i < kNumIcons; i++) {
  217.                 iconHandle = INFO.icons[i].iconData;
  218.                 if (iconHandle != NULL) {
  219.                     INFO.icons[i].iconData = NULL;
  220.                     DisposHandle(iconHandle);
  221.                     USER_STATUS = MemError();
  222.                     LogError('CLOS', USER_STATUS);
  223.                 }
  224.             }
  225.             /*
  226.              * Now, dump any directories that we have hanging around.
  227.              */
  228.             while (USER_STATUS == noErr) {
  229.                 /*
  230.                  * Get the next directory record. Exit if there
  231.                  * are no more. Else, close the associated
  232.                  * I/O process.
  233.                  */
  234.                 catalogInfoPtr = (CatalogInfoPtr)
  235.                             DequeueFirst(&INFO.catalogQHdr);
  236.                 if (catalogInfoPtr == NULL)
  237.                     break;
  238.                 LogRString('CLOS', &catalogInfoPtr->directoryName);
  239.                 USER_STATUS = ADASClosePAB(catalogInfoPtr->refNum);
  240.                 LogStatus('CLOS', USER_STATUS, "\pADASClosePAB");
  241.                 /*
  242.                  * Dispose of the directory record *before* checking
  243.                  * for a status error from ADASClosePAB()
  244.                  */
  245.                 DisposPtr((Ptr) catalogInfoPtr);
  246.                 if (USER_STATUS == noErr) {
  247.                     USER_STATUS = MemError();
  248.                     LogStatus('CLOS', USER_STATUS, "\pDisposPtr(catalogInfoPtr)");
  249.                 }
  250.             }
  251.             if (USER_STATUS == noErr) {
  252.                 /*
  253.                  * So far, so good. Make sure the queue header is
  254.                  * clean and dump the info pointer. Note that the
  255.                  * driver control pointer in DCTL.dCtlStorage still
  256.                  * contains infoPtr.
  257.                  */
  258.                 INFO.catalogQHdr.qHead = NULL;
  259.                 INFO.catalogQHdr.qTail = NULL;
  260.                 DisposPtr((Ptr) infoPtr);
  261.                 USER_STATUS = MemError();
  262.             }
  263.             /*
  264.              * If (and only if) we were able to dispose of the
  265.              * entire private storage area, we can finally clear
  266.              * the driver private storage pointer.
  267.              */
  268.             if (USER_STATUS == noErr)
  269.                 DCTL.dCtlStorage = NULL;
  270.         }
  271.         LogTextX('CLOS', "\pClose Exits");
  272.         return (USER_STATUS);
  273. }
  274.  
  275. /*
  276.  * DequeueFirst is a wrapper for the system Dequeue
  277.  * function that returns the first element from the
  278.  * queue, or NULL if the queue is empty. Note that
  279.  * an empty queue is not an error.
  280.  */
  281. QElemPtr
  282. DequeueFirst(
  283.         register QHdrPtr        theQueue
  284.     )
  285. {
  286.         register QElemPtr        result;
  287.  
  288.         result = theQueue->qHead;
  289.         if (result != NULL) {
  290.             /*
  291.              * Dequeue can fail if the first element in
  292.              * the queue was removed by an interrupt
  293.              * service routine. This is not an error.
  294.              * By working in this manner, we do not need
  295.              * to block interrupts (except when actually
  296.              * modifying the queue). In particular, the
  297.              * frequent case of querying an empty queue
  298.              * does not lock out interrupts.
  299.              */
  300.             if (Dequeue(result, theQueue) != noErr)
  301.                 result = NULL;
  302.         }
  303.         return (result);
  304. }
  305.  
  306.